#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "stdarg.h"

#include "BList.h"

#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"

#include "SpecialTerm.h"


FeatureTermContainer::FeatureTermContainer(Symbol *name,int p_value,int p_type,Ontology *o)
{
	m_name=name;
	m_reference_count=1;
	m_data_type=0;
	m_value.m_i.m_value=p_value;
	m_value.m_i.m_type=p_type;
	if (o!=0) m_sort=o->get_sort("integer");
   	     else m_sort=0;
} /* FeatureTermContainer::FeatureTermContainer */ 


FeatureTermContainer::FeatureTermContainer(Symbol *name,float p_value,int p_type,Ontology *o)
{
	m_name=name;
	m_reference_count=1;
	m_data_type=1;
	m_value.m_f.m_value=p_value;
	m_value.m_f.m_type=p_type;
	if (o!=0) m_sort=o->get_sort("float");
   	     else m_sort=0;
} /* FeatureTermContainer::FeatureTermContainer */ 


FeatureTermContainer::FeatureTermContainer(Symbol *name,Symbol *s,Ontology *o)
{
	m_name=name;
	m_reference_count=1;
	m_data_type=2;
	m_value.m_s=s;
	if (o!=0) m_sort=o->get_sort("symbol");
   	     else m_sort=0;
} /* FeatureTermContainer::FeatureTermContainer */ 


FeatureTermContainer::FeatureTermContainer(Symbol *name,Sort *sort,int nfeatures,va_list features)
{
	int i;
	Symbol *fname;
	FeatureTerm *fvalue;

	m_name=name;
	m_reference_count=1;
	m_data_type=sort->get_data_type();
	m_value.m_ft.m_feature_name=0;
	m_value.m_ft.m_feature_value=0;

	switch(m_data_type) {
	case 0: m_value.m_i.m_value=0;
			m_value.m_i.m_type=-1;
			break;
	case 1: m_value.m_f.m_value=0;
			m_value.m_f.m_type=-1;
			break;
	case 2: m_value.m_s=0;
			break;
	case 3:
			m_value.m_ft.m_feature_name=new List<Symbol>;
			m_value.m_ft.m_feature_value=new List<FeatureTerm>;
			for(i=0;i<nfeatures;i++) {
				fname=va_arg(features,Symbol *);
				fvalue=va_arg(features,FeatureTerm *);
				m_value.m_ft.m_feature_name->Add(fname);
				m_value.m_ft.m_feature_value->Add(fvalue);
			} /* for */ 
			break;	
	} /* switch */ 
	
	m_sort=sort;
} /* FeatureTermContainer::FeatureTermContainer */ 


FeatureTermContainer::FeatureTermContainer(char *name,Sort *sort,int nfeatures,va_list features)
{
	int i;
	char *fname_tmp;
	Symbol *fname;
	FeatureTerm *fvalue;

	if (name!=0) m_name=new Symbol(name);
			else m_name=0;
	m_reference_count=1;
	m_data_type=sort->get_data_type();
	m_value.m_ft.m_feature_name=0;
	m_value.m_ft.m_feature_value=0;

	switch(m_data_type) {
	case 0: m_value.m_i.m_value=0;
			m_value.m_i.m_type=-1;
			break;
	case 1: m_value.m_f.m_value=0;
			m_value.m_f.m_type=-1;
			break;
	case 2: m_value.m_s=0;
			break;
	case 3:
			m_value.m_ft.m_feature_name=new List<Symbol>;
			m_value.m_ft.m_feature_value=new List<FeatureTerm>;
			for(i=0;i<nfeatures;i++) {
				fname_tmp=va_arg(features,char *);
				fname=new Symbol(fname_tmp);
				fvalue=va_arg(features,FeatureTerm *);
				m_value.m_ft.m_feature_name->Add(fname);
				m_value.m_ft.m_feature_value->Add(fvalue);
			} /* for */ 
			break;	
	} /* switch */ 
	
	m_sort=sort;
} /* FeatureTermContainer::FeatureTermContainer */ 


FeatureTermContainer::FeatureTermContainer(Symbol *name,SpecialTerm *st,Sort *sort)
{
	m_name=name;
	m_reference_count=1;
	m_data_type=5;
	m_value.m_special=st;
	m_sort=sort;
} /* FeatureTermContainer::FeatureTermContainer */ 


FeatureTermContainer::FeatureTermContainer(Symbol *name)
{
	m_name=name;
	m_reference_count=1;
	m_data_type=4;
	m_value.m_set=new List<FeatureTerm>;
	m_sort=0;
} /* FeatureTermContainer::FeatureTermContainer */ 


FeatureTermContainer::~FeatureTermContainer()
{
	if (m_name!=0) delete m_name;
	switch(m_data_type) {
	case DATATYPE_SYMBOL:delete m_value.m_s;
		break;
	case DATATYPE_FEATURETERM:	delete m_value.m_ft.m_feature_name;
								delete m_value.m_ft.m_feature_value;
								break;
	case DATATYPE_SET:	delete m_value.m_set;
						break;
	case DATATYPE_SPECIAL:	delete m_value.m_special;
							break;
	} /* switch */ 
	m_sort=0;
} /* FeatureTermContainer::~FeatureTermContainer */ 




bool FeatureTermContainer::AddSetValue(FeatureTerm *value)
{
	if (m_data_type==4) return false;

	m_value.m_set->Add(value);

	return true;
} /* FeatureTermContainer::AddSetValue */ 




void FeatureTermContainer::num_of_references(FeatureTerm *ft,List<FeatureTermContainer> *l1,List<List<FeatureTerm> > *l2)
{
	{
		int pos;
		List<FeatureTerm> *ltmp;
		pos=l1->PositionRef(this);
		if (pos!=-1) {
			ltmp=l2->operator[](pos);
			if (!ltmp->MemberRefP(ft)) ltmp->Add(ft);
			return;
		} /* if */ 
	}

	l1->Add(this);
	{
		List<FeatureTerm> *ltmp;
		ltmp=new List<FeatureTerm>;
		ltmp->Add(ft);
		l2->Add(ltmp);
	}

	if (m_data_type==DATATYPE_FEATURETERM && m_value.m_ft.m_feature_value!=0) {
		FeatureTerm *ft;
		List<FeatureTerm> l_features;

		l_features.Instance(*(m_value.m_ft.m_feature_value));
		l_features.Rewind();
		while(l_features.Iterate(ft)) ft->m_ft->num_of_references(ft,l1,l2);
	} /* if */ 

	if (m_data_type==DATATYPE_SET && m_value.m_set!=0) {
		FeatureTerm *ft;
		List<FeatureTerm> l_set;

		l_set.Instance(*(m_value.m_set));
		l_set.Rewind();
		while(l_set.Iterate(ft)) ft->m_ft->num_of_references(ft,l1,l2);
	} /* if */ 

	if (m_data_type==DATATYPE_SPECIAL && m_value.m_special!=0) {
		FeatureTerm *ft;
		List<FeatureTerm> l_features;

		l_features.Instance(m_value.m_special->m_values);
		l_features.Rewind();
		while(l_features.Iterate(ft)) ft->m_ft->num_of_references(ft,l1,l2);
	} /* if */ 

} /* FeatureTermContainer::num_of_references_internal */ 
